package cn.skyisazure.metacompare.other;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.skyisazure.metacompare.sqlcompare.exceptions.MetaCompareException;
import lombok.Data;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * <pre>
 *     操作poolName数据源名称的统一入口:
 *      格式：app_{code}_{key}_{env}
 * </pre>
 * @author wangjj
 * @date 2023/10/7 14:53
 */
@Slf4j
public class PoolNameUtil {

    @Data
    public static class PoolInfo {
        /**数据源名*/
        private String dsPoolName;
        /**数据源类型*/
        private String dsDbType;
        /**dsQueryKey*/
        private String dsQueryKey;
        /**表名*/
        private String tableName;
        /**tableKey*/
        private String tableKey;

        private Integer env;

        /**dsCode*/
        private String dsCode;
    }


    /**
     * 根据表key获取数据源名（静态方法）
     * @param tableKey
     * @return
     */
    public static PoolInfo getPoolInfoByTableKey(Long appId,String tableKey, Integer env){
        JDBCUtil jdbcUtil = SpringUtil.getBean(JDBCUtil.class);
        String getDSInfoByTableKeySql ="SELECT ds.`ds_pool_name`,t.`code`,ds.`query_key`,ds.`db_type`,ds.`code` dsCode " +
                "FROM `meta_data_source` ds " +
                "LEFT JOIN meta_table t ON t.ds_key=ds.query_key " +
                "WHERE ds.deleted='0' AND ds.latest=1 AND t.deleted='0' AND ds.app_id=? AND ds.env=? AND t.latest=1 AND t.query_key = ?";
        LinkedHashMap<String, Object> entity = jdbcUtil.executeWithClose(executor -> executor.queryOneData(new SqlModel(getDSInfoByTableKeySql, Arrays.asList(appId,env,tableKey))));
        if (ObjUtil.isEmpty(entity)){
            throw new MetaCompareException("未找到数据源：{tabkeKey:"+tableKey+"},{env:"+env+"}");
        }
        String poolName = Convert.toStr(entity.get("ds_pool_name"));
        String tableName = Convert.toStr(entity.get("code"));
        String dsQueryKey = Convert.toStr(entity.get("query_key"));
        String dsDbType = Convert.toStr(entity.get("db_type"));
        String dsCode =  Convert.toStr(entity.get("dsCode"));
        PoolInfo poolInfo = new PoolInfo();
        poolInfo.setDsPoolName(poolName);
        poolInfo.setDsQueryKey(dsQueryKey);
        poolInfo.setTableName(tableName);
        poolInfo.setTableKey(tableKey);
        poolInfo.setDsDbType(dsDbType);
        poolInfo.setEnv(env);
        poolInfo.setDsCode(dsCode);
        return poolInfo;
    }

    /**
     * 拆解数据源名（poolName）<br/>
     * poolName格式：app_{appId(36进制)}_{code}_{key}_{env}（字段：ds_pool_name）
     * @param  poolName 库名、数据源名
     * @return
     */
    public static Map<String,Serializable> apartDSName(String poolName){
        if (!poolName.startsWith("app_")) {
            throw new RuntimeException("poolName格式错误："+poolName);
        }


        // System.out.println(poolName.substring(0, poolName.indexOf("_")));
        String[] elements = poolName.split("_");
        int length = elements.length;
        /*todo 后续不用旧数据源旧应用的时候删除（时工说可以保留，新的用不到）*/
// ==============Start==============
        if (length < 5){
            // 兼容旧数据源旧应用
            Map<String, Serializable> map = new HashMap<>();
            map.put("appId",0L);
            map.put("code",elements[1]);
            map.put("key",elements[2]);
            map.put("envStr",elements[3]);
            return map;
        }
// ==============End==============
        StringBuilder codeBuilder= new StringBuilder();
        Long appId = null;
        String key="";
        String envStr="";
        for (int i = 0; i < length; i++) {
            String e = elements[i];
            if (i==0) {// app固定不选取
            }else if (i==1){// 下标是1的肯定是appId
                // appId
                appId = Long.parseLong(e, 36);
            }else if (i==length-2){
                // tableKey
                key=e;
            }else if (i==length-1){
                // envStr
                envStr=e;
            }else {
                // code:用户填写的，可能带：_，补回：_
                codeBuilder.append(e).append("_");
            }
        }
        String code = codeBuilder.substring(0,codeBuilder.length()-1);

        Map<String, Serializable> map = new HashMap<>();
        map.put("appId",appId);
        map.put("code",code);
        map.put("key",key);
        map.put("envStr",envStr);
        return map;
    }

    /**
     * 拼接数据源名（poolName）
     * @param appId 应用Id
     * @param dsCode 数据源code
     * @param dsKey 数据源queryKey
     * @param env 数据源环境（1，2，4）
     * @return
     */
    public static String composeDSName(@NonNull Long appId,
                                       @NonNull String dsCode,
                                       @NonNull String dsKey,
                                       @NonNull Integer env){
        String envStr;
        switch (env){
            case 1:envStr="dev";break;
            case 2:envStr="test";break;
            case 4:envStr="prod";break;
            default:throw new MetaCompareException("不存在该环境env值：["+env+"]");
        }
        return StrUtil.format("app_{}_{}_{}_{}", Long.toString(appId,36), dsCode, dsKey, envStr);
    }

    public static void main(String[] args) {
        // Long转换为36进制字符 & 36进制字符转换为Long
        // System.out.println(Long.toString(1768513297917411328L, 36));
        // System.out.println(Long.parseLong("dfphn55bt8n4", 36));
        String s = "app_dfphn55bt8n4_tes_sssaa_52t_aoooossssaa_dev";
        System.out.println(apartDSName(s));
    }
}
